using System;
using EnvDTE;
using System.Collections;
using System.IO;

namespace NDocBuilder
{
	/// <summary>
	/// Contains assembly information for a <see cref="NDocProject"/>
	/// </summary>
	/// <remarks>
	/// Instances of this class are create by the <see cref="NDocProject"/> for: <br/>
	/// <ul>
	///	<li>The selected project</li>
	///	<li>Every project the selected project has a reference to.</li>
	/// </ul>
	/// <br/>
	/// Every instance must be a member of a NDocProject.
	/// </remarks>
	public class NDocAssembly
	{
		/// <summary>
		/// The constructor for NDocAssembly
		/// </summary>
		/// <param name="parent">The NDocProject that contains this assembly</param>
		/// <param name="project">The project that builds this assembly</param>
		public NDocAssembly(NDocProject parent, Project project)
		{
			Parent = parent;
			AsmProject = project;

			Validate();
		}

		private NDocProject m_Parent;
		/// <summary>
		/// The ndoc project this assembly belongs to
		/// </summary>
		public NDocProject Parent
		{
			get{return m_Parent;}
			set{m_Parent=value;}
		}

		private Project m_asmProject;
		/// <summary>
		/// The visual studio project this assembly belongs to
		/// </summary>
		public Project AsmProject
		{
			get{return m_asmProject;}
			set{m_asmProject=value;}
		}

		/// <summary>
		/// The local path of the project root location
		/// </summary>
		public string ProjectPath
		{
			get{return AsmProject.Properties.Item("FullPath").Value.ToString();}
		}

		/// <summary>
		/// The namespace of this project
		/// </summary>
		public string Namespace
		{
			get{return AsmProject.Properties.Item("DefaultNamespace").Value.ToString();}
		}

		/// <summary>
		/// The current configuration of the active project
		/// </summary>
		public Configuration ProjectConfig
		{
			get{return AsmProject.ConfigurationManager.ActiveConfiguration;}
		}

		/// <summary>
		/// The full path to the xml file containing the documentation
		/// </summary>
		public string XmlDocFilename
		{
			get
			{
				string str = ProjectConfig.Properties.Item("DocumentationFile").Value.ToString();

				if(str != "")
				{
					// Seems that when a path is included in the property the file is relative from the project location
					// Otherwise the file is located in the output folder

					if(str.IndexOfAny("\\/".ToCharArray()) != -1)
						str = Path.Combine(ProjectPath, str);
					else
						str = Path.Combine(ProjectPath, 
										   Path.Combine(ProjectConfig.Properties.Item("OutputPath").Value.ToString(), str));
				}

				return str;
			}
		}

		/// <summary>
		/// The full path to the assembly
		/// </summary>
		public string AssemblyFilename
		{
			get
			{
				return Path.Combine(ProjectPath,
                                    ProjectConfig.Properties.Item("OutputPath").Value.ToString() +
                                    AsmProject.Properties.Item("OutputFileName").Value.ToString()); 
			}
		}

		private void Validate()
		{
			Parent.OutputPane.OutputString("Validating assembly: \"" + AsmProject.Name + "\" ...\n");

			if(!File.Exists(AssemblyFilename)) // Check if the output assembly exists
			{
				throw(new Exception("Could not find the file: \"" + AssemblyFilename + "\".\n" +
									"Make sure the project \"" + AsmProject.Name + "\" compiles."));
			}

			if(!File.Exists(XmlDocFilename)) // Check if the xml documentation exists
			{
				throw(new Exception("Could not find the file: \"" + XmlDocFilename + "\".\n" +
									"Make sure XML documentation is generated for project \"" + AsmProject.Name + "\"."));
			}
		}
	}

	/// <summary>
	/// Collection class for the <see cref="NDocAssembly"/> class
	/// </summary>
	public class NDocAssemblyList : System.Collections.CollectionBase
	{
		/// <summary>
		/// Add a new <see cref="NDocAssembly"/> to the collection
		/// </summary>
		/// <param name="asm">The assembly to add</param>
		/// <returns>The index of the position in the list</returns>
		public int Add(NDocAssembly asm)
		{
			return List.Add(asm);
		}

		/// <summary>
		/// Get or set a <see cref="NDocAssembly "/> at the given index
		/// </summary>
		public NDocAssembly this[int nIdx]
		{
			get{return (NDocAssembly)List[nIdx];}
			set{List[nIdx] = value;}
		}
	}
}
